﻿//-----------------------------------------------------------------------------------------------------------
// Wbfs Engine (WBFSe) Project by Omega Frost 
// http://wbfse.codeplex.com/
//
// WBFSe is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using WBFSe.FormatApi;
using WBFSe.IO;
using WBFSe.Attributes;
using System.Collections.Generic;
using WBFSe.Builders;
using WBFSe.IO.Drives;
using System.IO;

namespace WBFSe
{
    /// <summary>
    /// Main engine interop class
    /// </summary>
    public static class WbfsEngine
    {
        /// <summary>
        /// Retrieves the formats loaded by the engine
        /// </summary>
        /// <returns></returns>
        internal static IWbfsFormat[] GetLoadedFormats()
        {
            return WbfsLoader.GetLoadedFormats();
        }

        /// <summary>
        /// Loads a format from an assembly
        /// </summary>
        /// <param name="assemblyPath">Full path of the Assembly</param>
        /// <param name="formatClassName">Format descriptor name</param>
        /// <returns>True on success, false if a format with the same extension is already loaded</returns>
        public static bool LoadFormatFromAssembly(string assemblyPath, string formatClassName)
        {
            return WbfsLoader.LoadFormatFromAssembly(assemblyPath, formatClassName);
        }

        /// <summary>
        /// Loads all the formats in an assembly
        /// </summary>
        /// <param name="assemblyPath">Full path of the Assembly</param>
        /// <returns>Number of loaded formats</returns>
        public static int LoadFormatsFromAssembly(string assemblyPath)
        {
            return WbfsLoader.LoadFormatsFromAssembly(assemblyPath);
        }

        /// <summary>
        /// Loads an especific file from a directory
        /// </summary>
        /// <param name="directory">Base path, \ terminated</param>
        /// <param name="filenames">list of the filenames in the directory</param>
        /// <param name="filename">The name of the file in the list to load</param>
        /// <param name="format">Optional format to load the file</param>
        /// <param name="file">Out file</param>
        /// <returns>True if there's a parser for the file and there's a game in it</returns>
        /// <exception cref="System.Exception">Format reader failure</exception>
        public static bool LoadGame(string directory, string[] filenames,
            string filename, IWbfsFormat format, out IWbfsFileInfo file)
        {
            if ((file = WbfsIndexing.GetFile(directory, filename)) == null)
            {
                if (!WbfsLoader.LoadGame(directory, filenames, filename, format, out file))
                    return false;

                WbfsIndexing.AddFile(file);
            }

            return true;
        }

        /// <summary>
        /// Loads an especific file from a directory
        /// </summary>
        /// <param name="directory">Base path, \ terminated</param>
        /// <param name="filename">The name of the file in the list to load</param>
        /// <param name="format">Optional format to load the file</param>
        /// <param name="file">Out file</param>
        /// <returns>True if there's a parser for the file and there's a game in it</returns>
        /// <exception cref="System.Exception">Format reader failure</exception>
        public static bool LoadGame(string directory, string filename,
            IWbfsFormat format, out IWbfsFileInfo file)
        {
            if ((file = WbfsIndexing.GetFile(directory, filename)) == null)
            {
                if (!WbfsLoader.LoadGame(directory, filename, format, out file))
                    return false;

                WbfsIndexing.AddFile(file);
            }

            return true;
        }

        /// <summary>
        /// Creates a temporary file
        /// </summary>
        /// <param name="directory">Destination folder</param>
        /// <param name="filename">Destination filename</param>
        /// <param name="source">Source game</param>
        /// <param name="format">Optional Source format</param>
        /// <param name="split">Optional Container split information</param>
        /// <exception cref="System.Exception">Format creator failure</exception>
        public static IWbfsFileInfo CreateTemporaryFile(String directory, String filename,
            IWbfsFileInfo source, IWbfsFormat format, SplitInfo split, BuildFlags flags)
        {
            IWbfsFileInfo file = WbfsIndexing.GetFile(directory, filename);
            if (file != null) throw new ArgumentException("The file already exists");

            file = WbfsLoader.CreateTemporaryFile(directory, filename, source, format, split, flags);
            WbfsIndexing.AddFile(file);
            
            return file;
        }

        /// <summary>
        /// Finishes the file creation
        /// </summary>
        /// <param name="temp">Temporary file</param>
        /// <param name="successful">The operation was successful</param>
        /// <returns>A new file, the same if it's not temporary or null if not successful</returns>
        /// <exception cref="System.Exception">Format reader failure</exception>
        public static IWbfsFileInfo ConsolidateTemporaryFile(IWbfsFileInfo temp, bool successful)
        {
            if (!temp.Temporary)
                return temp;

            WbfsIndexing.RemoveFile(temp);
            temp = WbfsLoader.ConsolidateTemporaryFile(temp, successful);
            if (successful) WbfsIndexing.AddFile(temp);

            return temp;
        }

        /// <summary>
        /// Returns the drive corresponding to a path
        /// </summary>
        /// <param name="path">Path</param>
        /// <returns>Drive</returns>
        /// <exception cref="System.Exception">On operation failure</exception>
        public static IWbfsDriveInfo GetDrive(String path)
        {
            return WbfsDevices.GetDrive(path);
        }

        /// <summary>
        /// Formats a drive as WBFS
        /// </summary>
        /// <param name="path">Destination drive</param>
        /// <returns>Formatted drive</returns>
        public static IWbfsDriveInfo FormatAsWbfs(string path)
        {
            return WbfsDevices.FormatAsWbfs(path);
        }

        /// <summary>
        /// Searches for matches in the index
        /// </summary>
        /// <param name="key">Key</param>
        /// <param name="mode">Search mode</param>
        /// <returns>List of matches</returns>
        public static List<IWbfsFileInfo> FindFiles(String key, SearchMode mode)
        {
            return WbfsIndexing.FindFiles(key, mode);
        }
    }
}
